/*
 * Copyright (c) 2023 iQi.Co.Ltd. All rights reserved.
 */
 
using System.Collections.Generic;
using NetProtocol.POD;
using NetProtocol.Enum;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;
using IQIGame.Onigao.Framework;
using System.Threading.Tasks;
using System;

namespace NetProtocol.Server {
	/// <summary>
	/// 关卡
	/// module : level
	/// </summary>
	public interface SNetLevel : INetServerModule {
		Dictionary<int, MessageHandler> INetServerModule.GetModuleFunction()
        {	
            return new()
            {
                { NetMessageId.level_requestEnter, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.level_requestEnter, "Recv->" + data.ToString());
#endif
		                RequestEnterRequest _data = (RequestEnterRequest)data;
						return CS_requestEnter(session, _data.requestPOD);
		            } 
            	},
                { NetMessageId.level_localRequestSave, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.level_localRequestSave, "Recv->" + data.ToString());
#endif
		                LocalRequestSaveRequest _data = (LocalRequestSaveRequest)data;
						return CS_localRequestSave(session, _data.requestSaveLevelPOD);
		            } 
            	},
                { NetMessageId.level_localNotifyEnterLevel, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.level_localNotifyEnterLevel, "Recv->" + data.ToString());
#endif
		                LocalNotifyEnterLevelRequest _data = (LocalNotifyEnterLevelRequest)data;
		                CS_localNotifyEnterLevel(session, _data.levelId);
		                return VoidMessageResult.Instance;
		            } 
            	},
                { NetMessageId.level_localNotifyExitLevel, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.level_localNotifyExitLevel, "Recv->" + data.ToString());
#endif
		                LocalNotifyExitLevelRequest _data = (LocalNotifyExitLevelRequest)data;
		                CS_localNotifyExitLevel(session, _data.levelId);
		                return VoidMessageResult.Instance;
		            } 
            	},
                { NetMessageId.level_localC2SNotifyDataSyncEvent, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.level_localC2SNotifyDataSyncEvent, "Recv->" + data.ToString());
#endif
		                LocalC2SNotifyDataSyncEventRequest _data = (LocalC2SNotifyDataSyncEventRequest)data;
		                CS_localC2SNotifyDataSyncEvent(session, _data.eventPOD);
		                return VoidMessageResult.Instance;
		            } 
            	},
                { NetMessageId.level_getLevelSaveData, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.level_getLevelSaveData, "Recv->" + data.ToString());
#endif
		                GetLevelSaveDataRequest _data = (GetLevelSaveDataRequest)data;
						return CS_getLevelSaveData(session, _data.levelCid);
		            } 
            	},
            };
        }
        
        Dictionary<int, Func<IReceiveMessage>> INetServerModule.GetModuleRequest() 
        {
	        return new ()
	        {
	        	{NetMessageId.level_requestEnter, ()=> new RequestEnterRequest()},
	        	{NetMessageId.level_localRequestSave, ()=> new LocalRequestSaveRequest()},
	        	{NetMessageId.level_localNotifyEnterLevel, ()=> new LocalNotifyEnterLevelRequest()},
	        	{NetMessageId.level_localNotifyExitLevel, ()=> new LocalNotifyExitLevelRequest()},
	        	{NetMessageId.level_localC2SNotifyDataSyncEvent, ()=> new LocalC2SNotifyDataSyncEventRequest()},
	        	{NetMessageId.level_getLevelSaveData, ()=> new GetLevelSaveDataRequest()},
	        };
	    }
        
#region Server-side Interface
		/// <summary>
        ///  请求进入关卡
        /// </summary>
	    protected RequestEnterResult CS_requestEnter(ISession session, RequestEnterLevelPOD requestPOD);
		/// <summary>
        ///  请求保存本地关卡 -- Save需要转发到Game服
        /// </summary>
	    protected LocalRequestSaveResult CS_localRequestSave(ISession session, RequestSaveLevelPOD requestSaveLevelPOD);
		/// <summary>
        ///  通知进入本地关卡	
        /// </summary>
    	protected bool CS_localNotifyEnterLevel(ISession session, long levelId);
		/// <summary>
        ///  通知离开本地关卡	
        /// </summary>
    	protected bool CS_localNotifyExitLevel(ISession session, long levelId);
		/// <summary>
        ///  关卡数据同步事件
        /// </summary>
    	protected bool CS_localC2SNotifyDataSyncEvent(ISession session, DataSyncEventPOD eventPOD);
		/// <summary>
        /// 获取关卡存档
        /// </summary>
	    protected GetLevelSaveDataResult CS_getLevelSaveData(ISession session, int levelCid);
#endregion
#region Client-side Interface
		/// <summary>
        ///  本地模式会异步走到 notifyCreateLevel
        /// </summary>
        public RequestEnterResult SC_requestEnterResult(Task<RequestEnterResult> future){return new RequestEnterResult(future);}
        public RequestEnterResult SC_requestEnterResult(int code){return new RequestEnterResult(code);}
		/// <summary>
        ///  保存成功/失败需要提示
        /// </summary>
        public LocalRequestSaveResult SC_localRequestSaveResult(Task<LocalRequestSaveResult> future){return new LocalRequestSaveResult(future);}
        public LocalRequestSaveResult SC_localRequestSaveResult(int code){return new LocalRequestSaveResult(code);}
		/// <summary>
        ///  通知创建本地关卡，并直接进入，进入后发送notifyEnterLevel
        /// </summary>
		public bool SC_localNotifyCreateLevel(ISession session, LogicPlayerPOD playerPOD, CreateLevelPOD createLevelPOD){
	        return NetProtocolHelper.SendMessage(session, new LocalNotifyCreateLevel(playerPOD, createLevelPOD));
	    }
	    public void SC_localNotifyCreateLevel_Broadcast(List<ISession> sessions, LogicPlayerPOD playerPOD, CreateLevelPOD createLevelPOD){
	        NetProtocolHelper.BroadcastMessage(sessions, new LocalNotifyCreateLevel(playerPOD, createLevelPOD));
	    }
		/// <summary>
        ///  通知退出本地关卡(强制踢出)
        /// </summary>
		public bool SC_localNotifyShutdownLevel(ISession session, long levelId){
	        return NetProtocolHelper.SendMessage(session, new LocalNotifyShutdownLevel(levelId));
	    }
	    public void SC_localNotifyShutdownLevel_Broadcast(List<ISession> sessions, long levelId){
	        NetProtocolHelper.BroadcastMessage(sessions, new LocalNotifyShutdownLevel(levelId));
	    }
		/// <summary>
        ///  关卡数据同步事件
        /// </summary>
		public bool SC_localS2CNotifyDataSyncEvent(ISession session, DataSyncEventPOD eventPOD){
	        return NetProtocolHelper.SendMessage(session, new LocalS2CNotifyDataSyncEvent(eventPOD));
	    }
	    public void SC_localS2CNotifyDataSyncEvent_Broadcast(List<ISession> sessions, DataSyncEventPOD eventPOD){
	        NetProtocolHelper.BroadcastMessage(sessions, new LocalS2CNotifyDataSyncEvent(eventPOD));
	    }
		/// <summary>
        /// 
        /// </summary>
        public GetLevelSaveDataResult SC_getLevelSaveDataResult(Task<GetLevelSaveDataResult> future){return new GetLevelSaveDataResult(future);}
        public GetLevelSaveDataResult SC_getLevelSaveDataResult(int code, GetLevelSavePOD saveData){return new GetLevelSaveDataResult(code, saveData);}
        public GetLevelSaveDataResult SC_getLevelSaveDataResult(int code){return new GetLevelSaveDataResult(code);}
#endregion

#region Messages
	public class RequestEnterResult : MessageResult {
	    public RequestEnterResult(Task<RequestEnterResult> future): base(future) { }
		public RequestEnterResult(int code): base(code) { }
		public new RequestEnterResult SetDelayCall(Action delayCall) { base.SetDelayCall(delayCall); return this; }
        public override MessageResult GetFutureResult(Task task) { return ((Task<RequestEnterResult>)task).Result; }
		public override int GetMessageId() {return NetMessageId.level_requestEnterResult;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.level_requestEnterResult;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_int(code);
			return si_p;
		}
		public override string ToString() {
    		return "Level.SC_requestEnterResult { "
			+ "code="
			+ code
			+" }";
		}
	}
	public class LocalRequestSaveResult : MessageResult {
	    public LocalRequestSaveResult(Task<LocalRequestSaveResult> future): base(future) { }
		public LocalRequestSaveResult(int code): base(code) { }
		public new LocalRequestSaveResult SetDelayCall(Action delayCall) { base.SetDelayCall(delayCall); return this; }
        public override MessageResult GetFutureResult(Task task) { return ((Task<LocalRequestSaveResult>)task).Result; }
		public override int GetMessageId() {return NetMessageId.level_localRequestSaveResult;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.level_localRequestSaveResult;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_int(code);
			return si_p;
		}
		public override string ToString() {
    		return "Level.SC_localRequestSaveResult { "
			+ "code="
			+ code
			+" }";
		}
	}
	public class LocalNotifyCreateLevel : MessageNotify {
		private LogicPlayerPOD playerPOD;
		private CreateLevelPOD createLevelPOD;
		public LocalNotifyCreateLevel(LogicPlayerPOD playerPOD, CreateLevelPOD createLevelPOD) {
		    this.playerPOD = playerPOD;
		    this.createLevelPOD = createLevelPOD;
		}
		public override int GetMessageId() {return NetMessageId.level_localNotifyCreateLevel;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.level_localNotifyCreateLevel;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_pod(playerPOD);
			_out.Write_pod(createLevelPOD);
			return si_p;
		}
		public override string ToString() {
			return "Level.SC_localNotifyCreateLevel { "
			+ "playerPOD="
			+ playerPOD
			+ ", createLevelPOD="
			+ createLevelPOD
			+" }";
		}
	}
	public class LocalNotifyShutdownLevel : MessageNotify {
		private long levelId;
		public LocalNotifyShutdownLevel(long levelId) {
		    this.levelId = levelId;
		}
		public override int GetMessageId() {return NetMessageId.level_localNotifyShutdownLevel;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.level_localNotifyShutdownLevel;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_long(levelId);
			return si_p;
		}
		public override string ToString() {
			return "Level.SC_localNotifyShutdownLevel { "
			+ "levelId="
			+ levelId
			+" }";
		}
	}
	public class LocalS2CNotifyDataSyncEvent : MessageNotify {
		private DataSyncEventPOD eventPOD;
		public LocalS2CNotifyDataSyncEvent(DataSyncEventPOD eventPOD) {
		    this.eventPOD = eventPOD;
		}
		public override int GetMessageId() {return NetMessageId.level_localS2CNotifyDataSyncEvent;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.level_localS2CNotifyDataSyncEvent;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_pod(eventPOD);
			return si_p;
		}
		public override string ToString() {
			return "Level.SC_localS2CNotifyDataSyncEvent { "
			+ "eventPOD="
			+ eventPOD
			+" }";
		}
	}
	public class GetLevelSaveDataResult : MessageResult {
	    private GetLevelSavePOD saveData;
	    public GetLevelSaveDataResult(Task<GetLevelSaveDataResult> future): base(future) { }
		public GetLevelSaveDataResult(int code): base(code) { }
		public new GetLevelSaveDataResult SetDelayCall(Action delayCall) { base.SetDelayCall(delayCall); return this; }
	    internal GetLevelSaveDataResult(int code, GetLevelSavePOD saveData){
	        this.code = code;
	        this.saveData = saveData;
	    }
        public override MessageResult GetFutureResult(Task task) { return ((Task<GetLevelSaveDataResult>)task).Result; }
		public override int GetMessageId() {return NetMessageId.level_getLevelSaveDataResult;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.level_getLevelSaveDataResult;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_int(code);
			_out.Write_pod(saveData);
			return si_p;
		}
		public override string ToString() {
    		return "Level.SC_getLevelSaveDataResult { "
			+ "code="
			+ code
			+ ", saveData="
			+ saveData
			+" }";
		}
	}
	private class RequestEnterRequest : IReceiveMessage
    {
		internal RequestEnterLevelPOD requestPOD;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            requestPOD = _in.HasRemaining() ? _in.Read_pod<RequestEnterLevelPOD>(RequestEnterLevelPOD.DynamicFactory) : default;
		}
        public int GetMessageId() { return NetMessageId.level_requestEnter; }
        public override string ToString()
        {
            return "Level.requestEnter"+ ", requestPOD="+ requestPOD;
        }
    }
	private class LocalRequestSaveRequest : IReceiveMessage
    {
		internal RequestSaveLevelPOD requestSaveLevelPOD;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            requestSaveLevelPOD = _in.HasRemaining() ? _in.Read_pod<RequestSaveLevelPOD>(RequestSaveLevelPOD.DynamicFactory) : default;
		}
        public int GetMessageId() { return NetMessageId.level_localRequestSave; }
        public override string ToString()
        {
            return "Level.localRequestSave"+ ", requestSaveLevelPOD="+ requestSaveLevelPOD;
        }
    }
	private class LocalNotifyEnterLevelRequest : IReceiveMessage
    {
		internal long levelId;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            levelId = _in.HasRemaining() ? _in.Read_long() : default;
		}
        public int GetMessageId() { return NetMessageId.level_localNotifyEnterLevel; }
        public override string ToString()
        {
            return "Level.localNotifyEnterLevel"+ ", levelId="+ levelId;
        }
    }
	private class LocalNotifyExitLevelRequest : IReceiveMessage
    {
		internal long levelId;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            levelId = _in.HasRemaining() ? _in.Read_long() : default;
		}
        public int GetMessageId() { return NetMessageId.level_localNotifyExitLevel; }
        public override string ToString()
        {
            return "Level.localNotifyExitLevel"+ ", levelId="+ levelId;
        }
    }
	private class LocalC2SNotifyDataSyncEventRequest : IReceiveMessage
    {
		internal DataSyncEventPOD eventPOD;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            eventPOD = _in.HasRemaining() ? _in.Read_pod<DataSyncEventPOD>(DataSyncEventPOD.DynamicFactory) : default;
		}
        public int GetMessageId() { return NetMessageId.level_localC2SNotifyDataSyncEvent; }
        public override string ToString()
        {
            return "Level.localC2SNotifyDataSyncEvent"+ ", eventPOD="+ eventPOD;
        }
    }
	private class GetLevelSaveDataRequest : IReceiveMessage
    {
		internal int levelCid;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            levelCid = _in.HasRemaining() ? _in.Read_int() : default;
		}
        public int GetMessageId() { return NetMessageId.level_getLevelSaveData; }
        public override string ToString()
        {
            return "Level.getLevelSaveData"+ ", levelCid="+ levelCid;
        }
    }
	}
#endregion
}